/* Zatok - язык программирования текстовых игр
 * (С) 2010 - 2012 Меркулов Матвей Юрьевич
 * Код лицензирован под лицензией GNU LGPL
 * Вы можете прочитать текст лицензии по адресу:
 * http://www.gnu.org/copyleft/lesser.html
 * или прочитать русский перевод по адресу:
 * http://ru.wikisource.org/wiki/GNU_Lesser_General_Public_License
 */

package base.userfunction;

import base.CProject;
import base.context.CContext;
import base.function.CFunction;
import base.value.CValue;
import base.value.userobject.CUserObject;

public class CFunctionCall extends CFunction {
	public CUserFunctionID FunctionID;
	public CValue ReturnedValue;

	
	
	public CFunctionCall( CUserFunctionID ID ) {
		FunctionID = ID;
	}
	
	

	@Override
	public CFunctionCall ToFunctionCall() {
		return this;
	}



	@Override
	public boolean ToBoolean() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.ToBoolean();
	}



	@Override
	public int ToInt() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.ToInt();
	}



	@Override
	public float ToFloat() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.ToFloat();
	}



	@Override
	public String ToString() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.ToString();
	}



	@Override
	public CUserObject ToObject() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.ToObject();
	}

	
	
	@Override
	public CValue GetValue() {
		Execute();
		if ( ReturnedValue == null ) Error( "Функция не возвратила значение" );
		return ReturnedValue.Clone();
	}



	@Override
	public void Execute() {
		CFunctionCall FunctionCall = new CFunctionCall( FunctionID );

		CUserFunction Function = null;
		if( CProject.CurrentObject != null ) Function = CProject.CurrentObject.BaseData.Functions.get( FunctionID );
		if( Function == null ) Function = CProject.RootObject.BaseData.Functions.get( FunctionID );
		if( Function == null ) Error( "Функция ''" + FunctionID.Name + "'' не найдена" );
		
		int ParamQuantity = Param.length;

		FunctionCall.Param = new CValue[ ParamQuantity ];
		for ( int N = 0; N < ParamQuantity; N++ ) {
			FunctionCall.Param[ N ] = Param[ N ].GetValue().Clone();
		}

		CFunctionCall OldCurrentFunctionCall = CProject.CurrentFunctionCall;
		CProject.CurrentFunctionCall = FunctionCall;
		CContext OldCurrentContext = CProject.CurrentContext;
		CProject.CurrentContext = new CContext();

		CProject.ExitStatus = CProject.EExitStatus.No;
		try {
			ExecuteModulesList( Function.Modules );
		} catch( StackOverflowError Exception ) {
			Error( "Бесконечный цикл вызова функций" );
		}
		CProject.ExitStatus = CProject.EExitStatus.No;

		CProject.CurrentContext = OldCurrentContext;
		CProject.CurrentFunctionCall = OldCurrentFunctionCall;
		ReturnedValue = FunctionCall.ReturnedValue;
	}
	
	
	
	@Override
	public String toString() {
		return FunctionID.Name;
	}
}
